package com.winning.sx.microframework.controller.sysmanage;

import com.fasterxml.jackson.databind.ObjectMapper;
import com.winning.dapi.data.entity.DataTable;
import com.winning.sx.microframework.common.shiro.UserToken;
import com.winning.sx.microframework.common.support.Ret;
import com.winning.sx.microframework.common.util.BaseUtil;
import com.winning.sx.microframework.common.util.Constains;
import com.winning.sx.microframework.common.util.EncryptionUtil;
import com.winning.sx.microframework.dao.sysmanage.LoginDao;
import com.winning.sx.microframework.model.LoginForm;
import com.winning.sx.microframework.model.manage.LoginSession;
import com.winning.sx.microframework.model.manage.OPLogModel;
import com.winning.sx.microframework.model.message.AjaxResponseMessage;
import com.winning.sx.microframework.model.message.AjaxTableResponseMessage;
import com.winning.sx.microframework.plugins.wx.WxConfig;
import com.winning.sx.microframework.service.EasyService;
import com.winning.sx.microframework.service.GenericApiService;
import com.winning.sx.microframework.service.base.UserService;
import net.sf.json.JSONObject;
import org.apache.shiro.SecurityUtils;
import org.apache.shiro.authc.*;
import org.apache.shiro.authz.UnauthorizedException;
import org.apache.shiro.session.Session;
import org.apache.shiro.subject.Subject;
import org.apache.shiro.web.util.SavedRequest;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Controller;
import org.springframework.ui.Model;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RequestMethod;
import org.springframework.web.bind.annotation.ResponseBody;
import org.springframework.web.servlet.ModelAndView;

import javax.servlet.http.HttpServletRequest;
import java.text.SimpleDateFormat;
import java.util.Date;
import java.util.HashMap;
import java.util.Map;

import static org.apache.shiro.web.util.WebUtils.SAVED_REQUEST_KEY;

/**
 * Created by xiaoY on 2016/12/9.
 */
@Controller
public class LoginController {
    @Autowired
    private LoginDao loginDao;
    @Autowired
    GenericApiService genericApiService;
    @Autowired
    EasyService easyService;
    @Autowired
    UserService userService;
    ObjectMapper objectMapper = new ObjectMapper();
    private static final Logger logger = LoggerFactory.getLogger(LoginController.class);

    @RequestMapping(value = {"/login"})
    public ModelAndView FirstLogin(HttpServletRequest request, Model model) {
        ModelAndView mv = new ModelAndView("login");
        mv.addObject("appId", WxConfig.appid);
        return mv;
    }

    @ResponseBody
    @RequestMapping(value = "/login/verifyUser")
    public AjaxResponseMessage doUserLogin(HttpServletRequest request, String datas) throws Exception {
        String ip = BaseUtil.getIPAddr(request);
        String time = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss").format(new Date());
        Map<String, String> param = null;
        if (datas != null)
            param = objectMapper.readValue(datas, Map.class);
        AjaxResponseMessage result = new AjaxResponseMessage();
        String msg = "";
        Subject subject = SecurityUtils.getSubject();
        LoginSession loginSession = (LoginSession) subject.getSession().getAttribute("loginSession");
        if (loginSession == null || loginSession.getcUserOpenId() == null || "".equals(loginSession.getcUserOpenId())) {
            //未通过微信登录的，那就是说是前台输入直接打开的页面，通过手机号和验证码直接登录的用户
            loginSession = new LoginSession();
            loginSession.setcUserID(param.get("telephone").toString());
            UserToken token = new UserToken(param.get("telephone").toString(), param.get("validCode").toString(), "CustomShiroRealm", "telephone");
            try {
                subject.login(token);
                if (subject.isAuthenticated()) {
                    Map staffParam = new HashMap();
                    staffParam.put("telephone", param.get("telephone"));
                    Map staff = easyService.queryEntity("BASE_staff", staffParam);

                    //认证成功 为他匹配身份并授予权限session
                    Map comParam = new HashMap();
                    comParam.put("id", staff.get("organizationId").toString());
                    Map com = easyService.queryEntity("BASE_Organization", comParam);
                    if(com==null){
                        msg="此人的所属机构信息异常！";
                        result.setSuccess(false);
                        result.setErrorMsg(msg);
                        return result;
                    }
                    String comName = com.get("name").toString();
                    String orgId = com.get("id").toString();
                    String superOrgId = com.get("superOrganizationId").toString();
                    if (!superOrgId.equals("0")) {
                        comParam.put("id", com.get("superOrganizationId").toString());
                        Map superCom = easyService.queryEntity("BASE_Organization", comParam);
                        comName = superCom.get("name").toString() + "-" + comName;
                    }

                    Map roleParam = new HashMap();
                    if("".equals(staff.get("role"))) staff.put("role","5");
                    roleParam.put("cRoleID", staff.get("role"));
                    Map role = easyService.querySql("select * from PM_ROLES where cRoleId=:cRoleID", roleParam).getDataRows().get(0);

                    loginSession.setStaffId(Integer.parseInt(staff.get("id").toString()));
                    loginSession.setOrgId(orgId);
                    loginSession.setcUserTelephone(staff.get("telephone").toString());
                    loginSession.setSuperOrgId(orgId);
                    loginSession.setOrgName(comName);
                    loginSession.setRoleId(staff.get("role").toString());
                    loginSession.setRoleName(role.get("cRoleName").toString());


                    SavedRequest savedRequest = (SavedRequest) subject.getSession().getAttribute(SAVED_REQUEST_KEY);
                    if (param.get("redirectUrl") == null && savedRequest != null)
                        param.put("redirectUrl", savedRequest.getRequestURI());
                    if (param.get("redirectUrl") == null)
                        param.put("redirectUrl", "userMain");
                    loginSession.setIndexUrl("userMain");
                    Session session = subject.getSession();
                    session.setAttribute("loginSession", loginSession);
                    result.setSuccess(true);
                    result.setCode("1");
                    if (param.get("redirectUrl").indexOf("userMain") > -1)
                        result.setErrorMsg("/userMain");
                    else if (param.get("redirectUrl").indexOf("edetail") > -1)
                        result.setErrorMsg(param.get("redirectUrl"));
                    else if (param.get("redirectUrl").indexOf("userInfo") > -1)
                        result.setErrorMsg(param.get("userInfo"));
                    else
                        result.setErrorMsg("/userMain");
                    return result;
                }
            } catch (IncorrectCredentialsException e) {
                msg = "验证码错误，或已失效";
                System.out.println(msg);
            } catch (UnknownAccountException e) {
                msg = "认证号不存在！";
                System.out.println(msg);
            }
        } else {
            //已经登录过了，那就是直接做一个授权认证
            Map staffParam = new HashMap();
            staffParam.put("telephone", param.get("telephone"));
            Map staff = easyService.queryEntity("BASE_staff", staffParam);
            if (staff!=null) {
                if (staff.get("validState").toString().equals(Constains.SYS_VALIDFLAG_TRUE)&&staff.get("validCode").toString().equals(param.get("validCode").toString())) {
                    //认证成功 为他匹配身份并授予权限session
                    Map comParam = new HashMap();
                    comParam.put("id", staff.get("organizationId").toString());
                    Map com = easyService.queryEntity("BASE_Organization", comParam);
                    if(com==null){
                        msg="此人的所属机构信息异常！";
                        result.setSuccess(false);
                        result.setErrorMsg(msg);
                        return result;
                    }
                    String comName = com.get("name").toString();
                    String orgId = com.get("id").toString();
                    String superOrgId = com.get("superOrganizationId").toString();
                    if (!superOrgId.equals("0")) {
                        comParam.put("id", com.get("superOrganizationId").toString());
                        Map superCom = easyService.queryEntity("BASE_Organization", comParam);
                        comName = superCom.get("name").toString() + "-" + comName;
                    }

                    Map roleParam = new HashMap();
                    if("".equals(staff.get("role"))) staff.put("role","5");
                    roleParam.put("cRoleID", staff.get("role"));
                    Map role = easyService.querySql("select * from PM_ROLES where cRoleId=:cRoleID", roleParam).getDataRows().get(0);

                    loginSession.setStaffId(Integer.parseInt(staff.get("id").toString()));
                    loginSession.setOrgId(orgId);
                    loginSession.setcUserTelephone(staff.get("telephone").toString());
                    loginSession.setSuperOrgId(orgId);
                    loginSession.setOrgName(comName);
                    loginSession.setRoleId(staff.get("role").toString());
                    loginSession.setRoleName(role.get("cRoleName").toString());

                    msg = "认证成功：您是" + com.get("name").toString() + "的" + role.get("cRoleName").toString();
                    if (WxConfig.validCodeTimeOut) {//更据数据库的配置 修改激活码de生效性 测试环境默认为false
                        Map update = new HashMap();
                        update.put("id", staff.get("id").toString());
                        update.put("validState", Constains.SYS_VALIDFLAG_FALSE);
                        easyService.update("BASE_staff", "id", update);

                    }
                    Map updateWx = new HashMap();
                    updateWx.put("staffId", staff.get("id").toString());
                    Map queryWx = new HashMap();
                    queryWx.put("openId", loginSession.getcUserOpenId());
                    easyService.update("PM_StaffWeChat", queryWx, updateWx);
                    //添加openId和staff的关联

                    result.setSuccess(true);
                    result.setCode("0");
                    result.setErrorMsg(msg);
                    return result;
                } else {
                    msg = "验证码错误，或已失效";
                }
            } else {
                msg = "认证号不存在！";
            }
        }

        result.setSuccess(false);
        result.setErrorMsg(msg);
        return result;
    }

    @ResponseBody
    @RequestMapping(value = "/login/verifyWx")
    public AjaxResponseMessage doUserWxLogin(HttpServletRequest request, String datas) throws Exception {
        String ip = BaseUtil.getIPAddr(request);
        String time = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss").format(new Date());
        Map<String, String> param = null;
        if (datas != null)
            param = objectMapper.readValue(datas, Map.class);

        AjaxResponseMessage result = new AjaxResponseMessage();
        String msg = "";
        String openId = param.get("userCode");
        com.alibaba.fastjson.JSONObject retJson = new com.alibaba.fastjson.JSONObject();
        if (openId == null) {
            //获取accessToken
            Map<String, String> wxMap = new HashMap<>();
            wxMap.put("serverName", "wx");
            wxMap.put("interfaceCode", "oauth2Access_token");
            wxMap.put("grant_type", "authorization_code");
            wxMap.put("appid", WxConfig.appid);
            wxMap.put("secret", WxConfig.appSecret);
            wxMap.put("code", param.get("code").toString());
            JSONObject jsonObject = JSONObject.fromObject(wxMap);
            Ret ret = genericApiService.send(jsonObject.toString(), GenericApiService.getIpAddress(request));
            Map retData = null;
            if (ret.isSuccess()) {
                retData = (Map) ret.getData();
                if (!"0000".equals(retData.get("code"))) {
                    ret.setErrorMsg(retData.get("msg").toString());
                    ret.setSuccess(false);
                    return ret;
                }
            } else {
                return ret;
            }
            retData = (Map) ret.getData();
            retJson = (com.alibaba.fastjson.JSONObject) com.alibaba.fastjson.JSONObject.parse(retData.get("result").toString());
            //获取用户信息
            wxMap = new HashMap<>();
            wxMap.put("serverName", "wx");
            wxMap.put("interfaceCode", "userinfo");
            wxMap.put("access_token", retJson.getString("access_token"));
            wxMap.put("openid", retJson.getString("openid"));
            wxMap.put("lang", "zh_CN");
            jsonObject = JSONObject.fromObject(wxMap);
            ret = genericApiService.send(jsonObject.toString(), GenericApiService.getIpAddress(request));

            if (ret.isSuccess()) {
                retData = (Map) ret.getData();
                if (!"0000".equals(retData.get("code"))) {
                    ret.setErrorMsg(retData.get("msg").toString());
                    ret.setSuccess(false);
                    return ret;
                }
            } else {
                return ret;
            }
            retData = (Map) ret.getData();
            retJson = (com.alibaba.fastjson.JSONObject) com.alibaba.fastjson.JSONObject.parse(retData.get("result").toString());
            openId = retJson.getString("openid");
        }
        //获取到用户的微信信息了
      /*
         1.查询openId是否已存在，如果存在那么查询staffId，如果staffId没有，那么就是没认证，否则就是认证过了。如果不存在，那么就是首次登陆，依然是没认证。
         2.保存openId 到 申请数据库
         */
        LoginSession loginSession = new LoginSession();
        try {
            param = new HashMap();
            param.put("openId", openId);
            param.put("validFlag", "100001");
            Map wxInfo = easyService.queryEntity("PM_StaffWeChat", param);
            if (wxInfo != null) {
                if ("199002".equals(wxInfo.get("state"))) {
                    result.setCode("9");
                } else {
                    loginSession.setcUserOpenId(openId);
                    loginSession.setStaffId(0);
                    loginSession.setRoleId("0");
                    loginSession.setOrgId("-9");
//                    loginSession.setcUserName(wxInfo.get("name").toString());
                    if (wxInfo.get("staffId") != null) {
                        result.setCode("4");
                        Map staffParam = new HashMap();
                        staffParam.put("id", wxInfo.get("staffId").toString());
                        Map entity = easyService.queryEntity("BASE_Staff", staffParam);
                        if (entity.size() > 0) {
                            loginSession.setRoleId(entity.get("role").toString());
                            loginSession.setStaffId(Integer.parseInt(entity.get("id").toString()));
                            loginSession.setOrgId(entity.get("organizationId").toString());
                            loginSession.setSuperOrgId(entity.get("organizationId").toString());
                            loginSession.setcUserName(entity.get("name").toString());
                        }
                        loginSession.setStaffId(Integer.parseInt(wxInfo.get("staffId").toString()));
                    } else
                        result.setCode("3");
                }

            } else {
                //插入新用户
                param = new HashMap<>();
                param.put("openId", openId);
                if (retJson != null) {
                    param.put("name", retJson.getString("nickname"));
                    param.put("headPhoto", retJson.getString("headimgurl"));
                }
                if (userService.registerNewCustomer(param)) {
                    loginSession.setcUserOpenId(openId);
                    loginSession.setStaffId(0);
                    loginSession.setRoleId("0");
                    loginSession.setOrgId("-9");
                    loginSession.setcUserName(retJson.getString("nickname"));
                    result.setCode("3");
                } else {
                    throw new Exception("创建用户失败");
                }
            }
        } catch (Exception e) {
            msg = e.getMessage();
        }


        UserToken token = new UserToken(openId, "", "CustomShiroRealm", "openid");
        Subject subject = SecurityUtils.getSubject();
        try {
            subject.login(token);
            if (subject.isAuthenticated()) {

                SavedRequest savedRequest = (SavedRequest) subject.getSession().getAttribute(SAVED_REQUEST_KEY);
                if (param.get("redirectUrl") == null && savedRequest != null)
                    param.put("redirectUrl", savedRequest.getRequestURI());
                if (param.get("redirectUrl") == null)
                    param.put("redirectUrl", "userMain");
                loginSession.setIndexUrl("userMain");
                Session session = subject.getSession();
                session.setAttribute("loginSession", loginSession);
                result.setSuccess(true);
                if (param.get("redirectUrl").indexOf("userMain") > -1)
                    result.setErrorMsg("/userMain?userCode=" + openId);
                else if (param.get("redirectUrl").indexOf("userInfo") > -1)
                    result.setErrorMsg(param.get("redirectUrl") + "?userCode=" + openId);
                else if (param.get("redirectUrl").indexOf("edetail") > -1)
                    result.setErrorMsg(param.get("redirectUrl") + "?userCode=" + openId);
                else
                    result.setErrorMsg("/userMain?userCode=" + openId);
                return result;
            }
        } catch (IncorrectCredentialsException e) {
            msg = "验证码错误";
            System.out.println(msg);
        } catch (UnknownAccountException e) {
            msg = "帐号不存在. There is no user with username of " + token.getPrincipal();
            System.out.println(msg);
        }
        result.setSuccess(false);
        result.setErrorMsg(msg);
        return result;
    }

    @RequestMapping(value = {"/admin"})
    public ModelAndView FirstAdmin(HttpServletRequest request, Model model) {
        ModelAndView mv = new ModelAndView("admin");
        return mv;
    }

    @ResponseBody
    @RequestMapping(value = "/login/verify")
    public AjaxResponseMessage doLogin(HttpServletRequest request, LoginForm userMessage, Model model) throws Exception {
        String ip = BaseUtil.getIPAddr(request);
        //String mac = getMACAddr(ip);
        String time = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss").format(new Date());
        OPLogModel opLog = new OPLogModel();
        opLog.setcIPAddr(ip);
        //opLog.setcMACAddr(mac);
        opLog.setcOpType("1");
        opLog.setdOpTime(time);
        AjaxResponseMessage result = new AjaxResponseMessage();
        String msg = "";
        userMessage.setPassword(EncryptionUtil.getHash(userMessage.getPassword()));

        String userCode = userMessage.getUsername();
        String password = userMessage.getPassword();
        String cSystemID = userMessage.getcSystemID();
        opLog.setcUserCode(userCode);
        opLog.setcOpSys(cSystemID);
        UserToken token = new UserToken(userCode, password, "WinningShiroRealm", "userCode");
        token.setRememberMe(false);
        Subject subject = SecurityUtils.getSubject();
        try {
            subject.login(token);
            if (subject.isAuthenticated()) {
                LoginSession loginSession = loginDao.getLoginUser(userCode);
                loginSession.setcSystemID(cSystemID);
                loginSession.setRoles(loginDao.getLoginRole(loginSession.getcUserID()));
                loginSession.setRoleId(loginSession.getRoles().get(0).getcRoleID());
                loginSession.setcPassword(userMessage.getPassword());

                loginSession.setIndexUrl("/welcome");

                Session session = subject.getSession();
                session.setAttribute("loginSession", loginSession);

                opLog.setcUserID(loginSession.getcUserID());
                opLog.setcUserName(loginSession.getcUserName());
                opLog.setbSuccess(1);

                //医保数据中心的用户数据获取
                Map param = new HashMap();
                param.put("cUserCode", loginSession.getcUserCode());
//                Map userInfo = staffService.getUserInfo(param);
//                loginSession.setsUserInfo(userInfo);

                loginDao.setOPLog(opLog);
                //session.setAttribute("cUserID", loginSession.getcUserID());
                //session.setAttribute("cUserCode", loginSession.getcUserCode());
                ////session.setAttribute("cUserName", userModel.getcUserName());
                ////session.setAttribute("cDeptID", userModel.getcDeptID());
                ////session.setAttribute("cDeptName", userModel.getcDeptName());
                ////session.setAttribute("systemid", cSystemID);
                String value = ((LoginSession) session.getAttribute("loginSession")).getcUserCode();
                if (value.equals(userCode)) {
                    logger.info("Retrieved the correct value! [" + userCode + "]");
                }
                result.setSuccess(true);
                return result;
            }
        } catch (IncorrectCredentialsException e) {
            opLog.setbSuccess(0);
            msg = "登录密码错误. Password for account " + token.getPrincipal() + " was incorrect.";
            model.addAttribute("message", msg);
            System.out.println(msg);
        } catch (ExcessiveAttemptsException e) {
            opLog.setbSuccess(0);
            msg = "登录失败次数过多";
            model.addAttribute("message", msg);
            System.out.println(msg);
        } catch (LockedAccountException e) {
            opLog.setbSuccess(0);
            msg = "帐号已被锁定. The account for username " + token.getPrincipal() + " was locked.";
            model.addAttribute("message", msg);
            System.out.println(msg);
        } catch (DisabledAccountException e) {
            opLog.setbSuccess(0);
            msg = "帐号已被禁用. The account for username " + token.getPrincipal() + " was disabled.";
            model.addAttribute("message", msg);
            System.out.println(msg);
        } catch (ExpiredCredentialsException e) {
            opLog.setbSuccess(0);
            msg = "帐号已过期. the account for username " + token.getPrincipal() + "  was expired.";
            model.addAttribute("message", msg);
            System.out.println(msg);
        } catch (UnknownAccountException e) {
            opLog.setbSuccess(0);
            msg = "帐号不存在. There is no user with username of " + token.getPrincipal();
            model.addAttribute("message", msg);
            System.out.println(msg);
        } catch (UnauthorizedException e) {
            opLog.setbSuccess(0);
            msg = "您没有得到相应的授权！" + e.getMessage();
            model.addAttribute("message", msg);
            System.out.println(msg);
        }
        loginDao.setOPLog(opLog);
        result.setSuccess(false);
        result.setErrorMsg(msg);
        return result;
    }

    @ResponseBody
    @RequestMapping(value = "/login/getsystemlist")
    public AjaxTableResponseMessage getSystemList(String datas) {
        AjaxTableResponseMessage ajaxResponseMessage = new AjaxTableResponseMessage();
        try {
            DataTable table = null;
            Map<String, Object> map = objectMapper.readValue(datas, Map.class);
            table = loginDao.getSystemList(map);
            ajaxResponseMessage.setDatas(table.getDataRows());
            ajaxResponseMessage.setTotalSize((int) table.getTotalRowNum());
            ajaxResponseMessage.setSuccess(true);
        } catch (Exception e) {
            ajaxResponseMessage.setErrorMsg("获取系统列表失败" + e.getMessage());
            ajaxResponseMessage.setSuccess(false);
        }
        return ajaxResponseMessage;
    }

    @RequestMapping(value = {"/logout"}, method = {RequestMethod.GET, RequestMethod.POST})
    public ModelAndView logout() throws Exception {
        Subject subject = SecurityUtils.getSubject();
        //if (subject.isAuthenticated())
        subject.logout();
        return new ModelAndView("redirect:/");
    }
}
